package service

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"strconv"
	"sync"
	"time"

	"gitee.com/wangshh_123/cross-pay-go/src/database"
	"gitee.com/wangshh_123/cross-pay-go/src/models"
	"gitee.com/wangshh_123/cross-pay-go/src/platform/providers/hlPay"
	hlpayModels "gitee.com/wangshh_123/cross-pay-go/src/platform/providers/hlPay/models"
	"gitee.com/wangshh_123/cross-pay-go/src/platform/providers/hlPay/services"

	"github.com/redis/go-redis/v9"
	"gorm.io/gorm"
)

// TransactionCacheService 交易数据缓存服务
type TransactionCacheService struct {
	hlpayClient *hlPay.HlPayClient
	redisClient *redis.Client
	db          *gorm.DB
	cacheMutex  sync.RWMutex
}

// NewTransactionCacheService 创建交易缓存服务
func NewTransactionCacheService(hlpayClient *hlPay.HlPayClient) *TransactionCacheService {
	return &TransactionCacheService{
		hlpayClient: hlpayClient,
		redisClient: database.RedisClient,
		db:          database.DB,
	}
}

// CachedTransaction 缓存的交易记录
type CachedTransaction struct {
	ID                  string `json:"id"`
	ClientTransactionId string `json:"clientTransactionId"`
	Company             string `json:"company"`
	CardID              string `json:"cardId"`
	CardNo              string `json:"cardNo"`
	TransactionNo       string `json:"transactionNo"`
	TransactionType     string `json:"transactionType"`
	Currency            string `json:"currency"`
	Amount              string `json:"amount"`
	TransactionAmount   string `json:"transactionAmount"`
	TransactionCurrency string `json:"transactionCurrency"`
	Fee                 string `json:"fee"`
	Status              string `json:"status"`
	TransactionTime     string `json:"transactionTime"`
	Detail              string `json:"detail"`
	Remark              string `json:"remark"`
	CreateTime          string `json:"createTime"`
	UserID              int64  `json:"user_id,omitempty"`
	MatrixAccount       string `json:"matrix_account,omitempty"`
}

// CacheResult 缓存结果
type CacheResult struct {
	TotalRecords   int                      `json:"total_records"`
	NewRecords     int                      `json:"new_records"`
	UpdatedRecords int                      `json:"updated_records"`
	CacheTime      time.Time                `json:"cache_time"`
	UserStats      map[int64]UserCacheStats `json:"user_stats"`
}

// UserCacheStats 用户缓存统计
type UserCacheStats struct {
	UserID           int64   `json:"user_id"`
	TransactionCount int     `json:"transaction_count"`
	TotalAmount      float64 `json:"total_amount"`
	Currency         string  `json:"currency"`
}

// SyncRecentTransactions 同步最近3天的交易数据到Redis
func (s *TransactionCacheService) SyncRecentTransactions(ctx context.Context) (*CacheResult, error) {
	s.cacheMutex.Lock()
	defer s.cacheMutex.Unlock()

	// 检查是否在120秒内已经同步过
	cacheKey := "transaction_cache:last_sync"
	lastSync, err := s.redisClient.Get(ctx, cacheKey).Result()
	if err == nil {
		lastSyncTime, err := time.Parse(time.RFC3339, lastSync)
		if err == nil && time.Since(lastSyncTime) < 120*time.Second {
			log.Printf("[TransactionCache] 120秒内已同步过，跳过本次同步")
			return &CacheResult{
				CacheTime: lastSyncTime,
			}, nil
		}
	}

	log.Printf("[TransactionCache] 开始同步最近3天的交易数据")

	// 计算时间范围
	endTime := time.Now()
	beginTime := endTime.AddDate(0, 0, -3) // 3天前

	// 获取交易数据
	transactions, err := s.fetchAllTransactions(ctx, beginTime.Format("2006-01-02"), endTime.Format("2006-01-02"))
	if err != nil {
		return nil, fmt.Errorf("获取交易数据失败: %v", err)
	}

	result := &CacheResult{
		TotalRecords: len(transactions),
		CacheTime:    time.Now(),
		UserStats:    make(map[int64]UserCacheStats),
	}

	// 批量处理交易记录
	if err := s.processTransactionsBatch(ctx, transactions, result); err != nil {
		return nil, fmt.Errorf("处理交易记录失败: %v", err)
	}

	// 更新最后同步时间
	s.redisClient.Set(ctx, cacheKey, time.Now().Format(time.RFC3339), 24*time.Hour)

	log.Printf("[TransactionCache] 同步完成，总记录: %d, 新记录: %d, 更新记录: %d",
		result.TotalRecords, result.NewRecords, result.UpdatedRecords)

	return result, nil
}

// fetchAllTransactions 获取所有交易记录
func (s *TransactionCacheService) fetchAllTransactions(ctx context.Context, beginTime, endTime string) ([]hlpayModels.CardTransactionDetailRow, error) {
	var allTransactions []hlpayModels.CardTransactionDetailRow
	pageSize := 1000
	pageIndex := 1

	for {
		params := &hlpayModels.CardTransactionDetailRequest{
			BeginTime: beginTime,
			EndTime:   endTime,
		}

		response, err := services.GetCardTransactionDetail(ctx, s.hlpayClient, params)
		if err != nil {
			return nil, fmt.Errorf("获取第 %d 页交易记录失败: %v", pageIndex, err)
		}

		if response.Code != 200 {
			return nil, fmt.Errorf("API返回错误，错误码: %d, 错误信息: %s", response.Code, response.Msg)
		}

		allTransactions = append(allTransactions, response.Rows...)
		log.Printf("[TransactionCache] 获取第 %d 页，记录数: %d", pageIndex, len(response.Rows))

		// 如果返回的记录数少于页面大小，说明已经获取完所有数据
		if len(response.Rows) < pageSize {
			break
		}

		pageIndex++
	}

	return allTransactions, nil
}

// processTransactionsBatch 批量处理交易记录
func (s *TransactionCacheService) processTransactionsBatch(ctx context.Context, transactions []hlpayModels.CardTransactionDetailRow, result *CacheResult) error {
	// 预热卡片用户映射缓存
	cardUserMap, err := s.getCardUserMapping(ctx)
	if err != nil {
		return fmt.Errorf("获取卡片用户映射失败: %v", err)
	}

	// 使用Pipeline批量处理
	pipe := s.redisClient.Pipeline()

	for _, transaction := range transactions {
		// 转换为缓存格式
		cachedTx := s.convertToCachedTransaction(transaction, cardUserMap)

		// 设置交易记录缓存
		txKey := fmt.Sprintf("transaction:%s", cachedTx.ID)
		txData, _ := json.Marshal(cachedTx)
		pipe.Set(ctx, txKey, txData, 7*24*time.Hour) // 缓存7天

		// 添加到卡片交易列表
		cardTxListKey := fmt.Sprintf("card_transactions:%s", cachedTx.CardID)
		pipe.ZAdd(ctx, cardTxListKey, redis.Z{
			Score:  float64(time.Now().Unix()),
			Member: cachedTx.ID,
		})
		pipe.Expire(ctx, cardTxListKey, 7*24*time.Hour)

		// 如果有用户ID，添加到用户交易列表
		if cachedTx.UserID > 0 {
			userTxListKey := fmt.Sprintf("user_transactions:%d", cachedTx.UserID)
			pipe.ZAdd(ctx, userTxListKey, redis.Z{
				Score:  float64(time.Now().Unix()),
				Member: cachedTx.ID,
			})
			pipe.Expire(ctx, userTxListKey, 7*24*time.Hour)

			// 更新用户统计
			s.updateUserStats(result, cachedTx)
		}

		// 添加到全局交易列表
		globalTxListKey := "global_transactions"
		pipe.ZAdd(ctx, globalTxListKey, redis.Z{
			Score:  float64(time.Now().Unix()),
			Member: cachedTx.ID,
		})
		pipe.Expire(ctx, globalTxListKey, 7*24*time.Hour)
	}

	// 执行批量操作
	_, err = pipe.Exec(ctx)
	if err != nil {
		return fmt.Errorf("批量缓存操作失败: %v", err)
	}

	result.NewRecords = len(transactions)
	return nil
}

// convertToCachedTransaction 转换为缓存交易记录
func (s *TransactionCacheService) convertToCachedTransaction(tx hlpayModels.CardTransactionDetailRow, cardUserMap map[string]int64) *CachedTransaction {
	cachedTx := &CachedTransaction{
		ID:                  fmt.Sprintf("%v", tx.ID),
		ClientTransactionId: tx.ClientTransactionId,
		Company:             tx.Company,
		CardID:              tx.CardId,
		CardNo:              tx.CardNo,
		TransactionType:     tx.TransactionType,
		Currency:            tx.Currency,
		Amount:              tx.Amount,
		Status:              tx.Status,
		TransactionTime:     tx.TransactionTime,
		Remark:              tx.Remark,
		CreateTime:          tx.CreateTime,
	}

	// 设置可选字段
	if tx.TransactionNo != nil {
		cachedTx.TransactionNo = *tx.TransactionNo
	}
	if tx.TransactionAmount != nil {
		cachedTx.TransactionAmount = *tx.TransactionAmount
	}
	if tx.TransactionCurrency != nil {
		cachedTx.TransactionCurrency = *tx.TransactionCurrency
	}
	if tx.Detail != nil {
		cachedTx.Detail = *tx.Detail
	}

	// 设置用户ID和矩阵账户
	if userID, exists := cardUserMap[tx.CardId]; exists {
		cachedTx.UserID = userID
		// 获取矩阵账户
		if matrixAccount, err := s.getMatrixAccountByUserID(userID); err == nil {
			cachedTx.MatrixAccount = matrixAccount
		}
	}

	return cachedTx
}

// getCardUserMapping 获取卡片用户映射
func (s *TransactionCacheService) getCardUserMapping(ctx context.Context) (map[string]int64, error) {
	// 先从Redis缓存获取
	cacheKey := "card_user_mapping"
	cachedData, err := s.redisClient.Get(ctx, cacheKey).Result()
	if err == nil {
		var mapping map[string]int64
		if json.Unmarshal([]byte(cachedData), &mapping) == nil {
			return mapping, nil
		}
	}

	// 从数据库获取
	var userCards []models.UserCard
	if err := s.db.Select("card_id, user_id").Find(&userCards).Error; err != nil {
		return nil, fmt.Errorf("查询用户卡片失败: %v", err)
	}

	mapping := make(map[string]int64)
	for _, userCard := range userCards {
		mapping[userCard.CardID] = userCard.UserID
	}

	// 缓存到Redis
	if mappingData, err := json.Marshal(mapping); err == nil {
		s.redisClient.Set(ctx, cacheKey, mappingData, 30*time.Minute)
	}

	return mapping, nil
}

// getMatrixAccountByUserID 根据用户ID获取矩阵账户
func (s *TransactionCacheService) getMatrixAccountByUserID(userID int64) (string, error) {
	var userMatrixAccount models.UserMatrixAccount
	if err := s.db.Where("user_id = ?", userID).Select("matrix_account").First(&userMatrixAccount).Error; err != nil {
		return "", err
	}
	return userMatrixAccount.MatrixAccount, nil
}

// updateUserStats 更新用户统计
func (s *TransactionCacheService) updateUserStats(result *CacheResult, tx *CachedTransaction) {
	if tx.UserID <= 0 {
		return
	}

	amount, _ := strconv.ParseFloat(tx.Amount, 64)

	if stats, exists := result.UserStats[tx.UserID]; exists {
		stats.TransactionCount++
		stats.TotalAmount += amount
		result.UserStats[tx.UserID] = stats
	} else {
		result.UserStats[tx.UserID] = UserCacheStats{
			UserID:           tx.UserID,
			TransactionCount: 1,
			TotalAmount:      amount,
			Currency:         tx.Currency,
		}
	}
}

// GetUserTransactions 获取用户交易记录
func (s *TransactionCacheService) GetUserTransactions(ctx context.Context, userID int64, limit int) ([]*CachedTransaction, error) {
	if limit <= 0 {
		limit = 50
	}

	// 获取用户交易ID列表
	userTxListKey := fmt.Sprintf("user_transactions:%d", userID)
	txIDs, err := s.redisClient.ZRevRange(ctx, userTxListKey, 0, int64(limit-1)).Result()
	if err != nil {
		return nil, fmt.Errorf("获取用户交易ID列表失败: %v", err)
	}

	// 批量获取交易详情
	var transactions []*CachedTransaction
	for _, txID := range txIDs {
		txKey := fmt.Sprintf("transaction:%s", txID)
		txData, err := s.redisClient.Get(ctx, txKey).Result()
		if err != nil {
			continue
		}

		var tx CachedTransaction
		if json.Unmarshal([]byte(txData), &tx) == nil {
			transactions = append(transactions, &tx)
		}
	}

	return transactions, nil
}

// GetCardTransactions 获取卡片交易记录
func (s *TransactionCacheService) GetCardTransactions(ctx context.Context, cardID string, limit int) ([]*CachedTransaction, error) {
	if limit <= 0 {
		limit = 50
	}

	// 获取卡片交易ID列表
	cardTxListKey := fmt.Sprintf("card_transactions:%s", cardID)
	txIDs, err := s.redisClient.ZRevRange(ctx, cardTxListKey, 0, int64(limit-1)).Result()
	if err != nil {
		return nil, fmt.Errorf("获取卡片交易ID列表失败: %v", err)
	}

	// 批量获取交易详情
	var transactions []*CachedTransaction
	for _, txID := range txIDs {
		txKey := fmt.Sprintf("transaction:%s", txID)
		txData, err := s.redisClient.Get(ctx, txKey).Result()
		if err != nil {
			continue
		}

		var tx CachedTransaction
		if json.Unmarshal([]byte(txData), &tx) == nil {
			transactions = append(transactions, &tx)
		}
	}

	return transactions, nil
}

// GetTransactionByID 根据ID获取交易记录
func (s *TransactionCacheService) GetTransactionByID(ctx context.Context, txID string) (*CachedTransaction, error) {
	txKey := fmt.Sprintf("transaction:%s", txID)
	txData, err := s.redisClient.Get(ctx, txKey).Result()
	if err != nil {
		return nil, fmt.Errorf("交易记录不存在: %v", err)
	}

	var tx CachedTransaction
	if err := json.Unmarshal([]byte(txData), &tx); err != nil {
		return nil, fmt.Errorf("解析交易记录失败: %v", err)
	}

	return &tx, nil
}

// GetCacheStats 获取缓存统计信息
func (s *TransactionCacheService) GetCacheStats(ctx context.Context) (map[string]interface{}, error) {
	stats := make(map[string]interface{})

	// 获取全局交易数量
	globalCount, err := s.redisClient.ZCard(ctx, "global_transactions").Result()
	if err == nil {
		stats["global_transaction_count"] = globalCount
	}

	// 获取最后同步时间
	lastSync, err := s.redisClient.Get(ctx, "transaction_cache:last_sync").Result()
	if err == nil {
		stats["last_sync_time"] = lastSync
	}

	// 获取缓存键数量
	keys, err := s.redisClient.Keys(ctx, "transaction:*").Result()
	if err == nil {
		stats["cached_transaction_count"] = len(keys)
	}

	return stats, nil
}

// ClearCache 清理缓存
func (s *TransactionCacheService) ClearCache(ctx context.Context) error {
	// 删除所有交易相关缓存
	patterns := []string{
		"transaction:*",
		"card_transactions:*",
		"user_transactions:*",
		"global_transactions",
		"transaction_cache:*",
		"card_user_mapping",
	}

	for _, pattern := range patterns {
		keys, err := s.redisClient.Keys(ctx, pattern).Result()
		if err != nil {
			continue
		}
		if len(keys) > 0 {
			s.redisClient.Del(ctx, keys...)
		}
	}

	log.Printf("[TransactionCache] 缓存清理完成")
	return nil
}
